Select URL API로 광고 소재 순환게재

Select URL API를 사용하여 Shared Storage를 활용하여 사용자가 사이트에서 보게 되는 광고 소재를 결정합니다.

광고주 또는 콘텐츠 제작자는 캠페인에 다양한 콘텐츠 순환 전략을 적용하고 콘텐츠 또는 광고 소재를 순환하여 효과를 높이고자 할 수 있습니다. Select URL API를 사용하면 여러 사이트에서 순차 회전, 균등하게 분산된 회전과 같은 다양한 회전 전략을 실행할 수 있습니다.

Select URL API 광고 소재 순환을 사용하면 광고 소재 ID, 조회수, 사용자 상호작용과 같은 데이터를 저장하여 사용자가 여러 사이트에서 어떤 광고 소재를 보게 될지 결정할 수 있습니다.

기본 API 및 선택 작동 방식에 관한 자세한 내용은 Select URL API 문서를 살펴보세요.

광고 소재 순환게재 사용해 보기

광고 소재 순환을 실험하려면 Select URL API와 Shared Storage가 사용 설정되어 있는지 확인하세요.

  • chrome://settings/content/siteData에서 Allow sites to save data on your device 또는 Delete data sites have saved to your device when you close all windows를 선택합니다.
  • chrome://settings/adPrivacy/sites에서 Site-suggested ads을 선택합니다.

이 문서의 코드 샘플 실시간 버전을 확인하려면 공유 저장소 라이브 데모를 사용해 보세요.

코드 샘플을 사용한 데모

이 예에서는 다음과 같이 정의됩니다.

  • creative-rotation.js는 회전할 콘텐츠를 정의하는 서드 파티 스크립트로, 이 예의 가중치와 같이 선택하여 표시할 다음 콘텐츠를 결정하는 모든 데이터를 포함합니다. 게시자 페이지에서 이 스크립트를 실행합니다. 이 스크립트는 공유 저장소 워크렛을 호출하여 저장소에 있는 사용 가능한 데이터와 선택할 URL 목록을 기반으로 표시할 콘텐츠를 결정합니다.

  • creative-rotation-worklet.js는 순환 전략을 조회하고 다음에 게시할 콘텐츠를 계산하여 해당 콘텐츠를 반환하는 서드 파티의 공유 저장소 워크렛입니다.

데모 작동 방식

  1. 사용자가 게시자 페이지를 방문하면 페이지에서 서드 파티의 creative-rotation.js 스크립트를 로드합니다. 광고 소재 순환 스크립트는 공유 저장소 워크렛을 로드하고 실행합니다. 스크립트는 선택할 URL 목록을 워크렛 호출에 제공합니다.
  2. 워크렛에서 공유 저장소가 아직 초기화되지 않은 경우 초기 광고 로테이션 전략 및 광고 색인으로 저장소가 초기화됩니다. 이 데모에 사용된 초기 순환 전략은 순차 전략입니다.
  3. 워크렛은 공유 저장소에서 순환 모드를 읽고 다음 광고의 색인을 반환합니다. 순차 순환 모드의 경우 다음 호출에 사용할 새 값으로 공유 저장소의 광고 항목 색인을 업데이트합니다.워크렛은 selectURL를 호출할 때 사용된 resolveToConfig 값을 기반으로 FencedFrameConfig 또는 불투명 URN 객체를 반환합니다.
  4. creative-rotation 스크립트는 선택한 광고를 격리된 프레임 또는 iframe에 표시합니다. 반환 유형에 관한 자세한 내용은 광고 렌더링 문서를 참고하세요.
  5. 사용자가 회전 모드를 변경하면 공유 저장소 워크렛이 공유 저장소에 저장된 광고 소재 회전 모드 값을 업데이트합니다.
  6. 게시자 페이지를 새로고침하면 1~4단계가 반복되어 선택한 순환 전략에 따라 표시할 다음 광고를 선택할 수 있습니다.

코드 샘플

다음은 creative-rotation.jscreative-rotation-worklet.js의 코드 샘플입니다.

creative-rotation.js

const contentProducerUrl = 'https://your-server.example';

// Ad config with the URL of the ad, a probability weight for rotation, and the clickthrough rate.
const DEMO_AD_CONFIG = [
  {
    url: `${contentProducerUrl}/ads/ad-1.html`,
    weight: 0.7,
  },
  {
    url: `${contentProducerUrl}/ads/ad-2.html`,
    weight: 0.2,
  },
  {
    url: `${contentProducerUrl}/ads/ad-3.html`,
    weight: 0.1,
  },
];

async function setRotationMode(rotationMode) {
  // Load the worklet module
  const creativeRotationWorklet = await window.sharedStorage.createWorklet(
    `${contentProducerUrl}/url-selection/creative-rotation-worklet.js`,
    { dataOrigin: 'script-origin' }
  );

  await creativeRotationWorklet.run('set-rotation-mode', {
    data: { rotationMode }
  });
  console.log(`creative rotation mode set to ${rotationMode}`);
}

async function injectAd() {
  // Load the worklet module
  const creativeRotationWorklet = await window.sharedStorage.createWorklet(
    `${contentProducerUrl}/url-selection/creative-rotation-worklet.js`,
    { dataOrigin: 'script-origin' }
  );

  const urls = DEMO_AD_CONFIG.map(({ url }) => ({ url }));

  // Resolve the selectURL call to a fenced frame config only when it exists on the page
  const resolveToConfig = typeof window.FencedFrameConfig !== 'undefined';

  // Run the URL selection operation to determine the next ad that should be rendered
  const selectedUrl = await creativeRotationWorklet.selectURL('creative-rotation', urls, {
    data: DEMO_AD_CONFIG,
    resolveToConfig
  });

  const adSlot = document.getElementById('ad-slot');

  if (resolveToConfig && selectedUrl instanceof FencedFrameConfig) {
    adSlot.config = selectedUrl;
  } else {
    adSlot.src = selectedUrl;
  }
}

injectAd();

creative-rotation-worklet.js

class SelectURLOperation {
  async run(urls, data) {
    // Initially set the storage to sequential mode for the demo
    await SelectURLOperation.seedStorage();

    // Read the rotation mode from Shared Storage
    const rotationMode = await sharedStorage.get('creative-rotation-mode');

    // Generate a random number to be used for rotation
    const randomNumber = Math.random();

    let index;

    switch (rotationMode) {
      /**
       * Sequential rotation
       * - Rotates the creatives in order
       * - Example: A -> B -> C -> A ...
       */
      case 'sequential':
        const currentIndex = await sharedStorage.get('creative-rotation-index');
        index = parseInt(currentIndex, 10);
        const nextIndex = (index + 1) % urls.length;

        console.log(`index = ${index} / next index = ${nextIndex}`);

        await sharedStorage.set('creative-rotation-index', nextIndex.toString());
        break;

      /**
       * Evenly-distributed rotation
       * - Rotates the creatives with equal probability
       * - Example: A=33% / B=33% / C=33%
       */
      case 'even-distribution':
        index = Math.floor(randomNumber * urls.length);
        break;

      /**
       * Weighted rotation
       * - Rotates the creatives with weighted probability
       * - Example: A=70% / B=20% / C=10%
       */
      case 'weighted-distribution':
        console.log('data = ', JSON.stringify(data));
        // Find the first URL where the cumnulative sum of the weights
        // exceed the random number. The array is sorted by the weight
        // in descending order.
        let weightSum = 0;
        const { url } = data
          .sort((a, b) => b.weight - a.weight)
          .find(({ weight }) => {
            weightSum += weight;
            return weightSum > randomNumber;
          });

        index = urls.indexOf(url);
        break;

      default:
        index = 0;
    }

    console.log(JSON.stringify({ index, randomNumber, rotationMode }));
    return index;
  }

  // Set the mode to sequential and set the starting index to 0.
  static async seedStorage() {
    await sharedStorage.set('creative-rotation-mode', 'sequential', {
      ignoreIfPresent: true,
    });

    await sharedStorage.set('creative-rotation-index', 0, {
      ignoreIfPresent: true,
    });
  }
}

class SetRotationModeOperation {
  async run({ rotationMode }) {
    await sharedStorage.set('creative-rotation-mode', rotationMode);
  }
}

// Register the operation as 'creative-rotation'
register('creative-rotation', SelectURLOperation);
register('set-rotation-mode', SetRotationModeOperation);

스크린샷이 포함된 워크스루

  1. Select URL API 및 공유 저장소를 사용하여 광고 소재 순환에 액세스하려면 https://shared-storage-demo.web.app/으로 이동하세요. '광고 소재 순환게재' 데모를 선택합니다.

  2. '게시자 A'로 데모를 살펴봅니다. https://shared-storage-demo-publisher-a.web.app/creative-rotation으로 리디렉션됩니다. 페이지는 Select URL API를 통해 액세스하는 Shared Storage에 저장된 광고 소재 순환 데이터를 기반으로 번호가 매겨진 콘텐츠를 로드합니다. 광고 소재 순환게재의 데모 모드는 순차, 균등 배포, 가중치 배포입니다. 워크렛은 로직을 실행하여 iframe에 표시되는 콘텐츠를 선택합니다. 다음 이미지는 게시자 페이지를 보여줍니다. 1의 이미지가 포함된 iframe과 광고 로테이션 전략(연속, 균등 분포, 가중치 분포)을 선택하는 컨트롤이 포함된 게시자 A의 페이지 콘텐츠(https://shared-storage-demo-publisher-a.web.app/creative-rotation)를 보여주는 스크린샷 다양한 광고 소재 순환 전략을 설명하는 텍스트 영역과 iframe 및 워크렛 로직 링크도 있습니다.

    스크린샷에는 1의 이미지와 광고 소재 순환 전략을 선택하는 컨트롤이 있는 게시자 A 페이지가 표시되어 있습니다.

  3. 공유 저장소에 저장된 항목을 보려면 Chrome DevTools에서 애플리케이션 -> 공유 저장소로 이동합니다. 공유 저장소에 항목 2개가 생성됩니다. https://shared-storage-demo-publisher-a.web.app 출처에 빈 저장소를 사용할 수 있습니다. 여기에는 해당 출처에 관한 저장소가 포함되며 게시자가 공유 저장소에 쓸 필요가 없으므로 데모에서는 비어 있게 됩니다. 나중에 데모를 위해 해당 페이지를 방문하면 게시자 B에 대해 유사한 저장소가 생성됩니다. Chrome DevTools, 특히 애플리케이션 섹션을 보여주는 스크린샷으로, 공유 저장소 항목이 강조 표시되어 있고 '게시자 A'의 출처인 https://shared-storage-demo-publisher-a.web.app의 빈 저장소가 표시되어 있습니다.

    Chrome DevTools에 게시자 A의 공유 저장소가 비어 있는 것으로 표시됩니다.

  4. https://shared-storage-demo-content-producer.web.app 출처에 다른 공유 저장소 항목이 생성됩니다. 게시자 페이지에 삽입된 서드 파티 iframe의 저장소입니다. 이 저장소는 광고 소재 선택을 조정하기 위해 사용 가능한 두 게시자 간에 데이터를 공유하는 데 사용됩니다. 이 공유 저장소는 두 개의 키-값 쌍을 저장하여 표시된 광고 소재 및 순환 전략에 관한 정보를 저장하는 데 사용됩니다. 데모에 사용된 첫 번째 키는 creative-rotation-index이며 값은 순차 모드의 현재 광고 소재 색인입니다. 두 번째 키는 사용되는 순환 전략을 지정하는 creative-rotation-mode입니다. Chrome Devtools, 특히 출처 https://shared-storage-demo-content-producer.web.app의 공유 저장소를 보여주는 스크린샷입니다. 저장소는 비어 있지 않으며 저장된 키-값 쌍이 2개 표시됩니다. 첫 번째 키는 값이 1인 creative-rotation-index입니다. 저장된 두 번째 키는 값이 'sequential'인 creative-rotation-mode입니다.

    스크린샷에는 creative-rotation-index: 1 및 creative-rotation-mode: 'sequential'이라는 두 개의 키-값 쌍이 있는 Chrome DevTools 공유 저장소가 표시되어 있습니다.

  5. 순차 모드에서 페이지를 새로고침하면 1, 2, 3, 1, … 순으로 다음 광고 소재가 표시됩니다. 순차 모드에서 표시되는 광고 소재의 색인에 따라 키 creative-rotation-index의 값이 변경됩니다. '게시자 A' 웹페이지와 공유 저장소 섹션을 보여주는 DevTools를 보여주는 스크린샷 페이지의 광고 소재에는 2라는 라벨이 지정되어 있고 키 creative-rotation-index의 값은 표시된 광고 소재의 색인과 일치하는 2로 강조표시되어 있습니다. 현재 creative-rotation-mode가 순차로 표시됩니다.

    게시자 A의 웹페이지와 DevTools를 보여주는 스크린샷 표시된 광고 소재는 2이고 creative-rotation-mode는 순차이며 creative-rotation-index는 2입니다.

  6. 컨트롤 버튼을 사용하여 광고 소재 순환게재 모드를 변경하면 키 creative-rotation-mode의 값이 해당 전략으로 업데이트됩니다. 이는 워크렛 코드에서 iframe에 표시할 다음 광고 소재를 선택하는 데 사용됩니다. creative-rotation-index에 저장된 값은 순차 외의 회전 모드에서는 변경되지 않습니다. '게시자 A' 웹페이지와 공유 저장소 섹션을 보여주는 DevTools를 보여주는 스크린샷 페이지의 광고 소재가 1로 표시됩니다. creative-rotation-mode가 가중치 적용 배포로 설정되어 있고 순환 모드를 가중치 적용 배포로 설정하는 해당 컨트롤이 강조 표시되어 있습니다. 순차 외의 순환 모드에서는 색인이 사용되거나 업데이트되지 않으므로 표시된 광고 소재는 1이지만 creative-rotation-index의 값은 2입니다.

    게시자 A의 웹페이지와 DevTools를 보여주는 스크린샷 표시된 광고 소재는 1이고 creative-rotation-mode는 가중치 분포이며 creative-rotation-index는 2 (사용되지 않음)입니다.

  7. https://shared-storage-demo-publisher-b.web.app/creative-rotation에서 '게시자 B' 페이지로 이동합니다. 순차 모드에서는 '게시자 A'의 URL을 방문할 때 표시되는 시퀀스의 다음 광고 소재가 표시되어야 합니다. 콘텐츠 제작자의 공유 저장소를 검사하면 '게시자 A'와 '게시자 B'가 모두 동일한 저장소를 공유하고 있으며, 이 저장소의 설정을 사용하여 표시할 다음 광고 소재와 사용할 순환 전략을 선택하고 있는 것을 확인할 수 있습니다. '게시자 B' 웹페이지와 출처 https://shared-storage-demo-content-producer.web.app의 공유 저장소 섹션을 보여주는 DevTools를 보여주는 스크린샷입니다. 페이지의 광고 소재는 3으로 표시됩니다. 강조 표시된 creative-rotation 색인은 3이고 creative-rotation-mode는 sequential입니다.

    게시자 B의 웹페이지 및 DevTools 공유 저장소 광고 소재는 3이고, 광고 소재 순환 색인은 3이며, 광고 소재 순환 모드는 순차입니다.

  8. '게시자 B'의 공유 저장소는 '게시자 A'의 공유 저장소와 마찬가지로 비어 있습니다.  Chrome DevTools, 특히 애플리케이션 섹션을 보여주는 스크린샷. 공유 저장소 항목이 강조 표시되어 있고 '게시자 B'의 출처(https://shared-storage-demo-publisher-b.web.app)에 빈 저장소가 표시되어 있습니다.

    Chrome DevTools에 게시자 B 출처의 빈 공유 저장소가 표시됨

    사용 사례

    Select URL API의 사용 가능한 모든 사용 사례는 이 섹션에서 확인할 수 있습니다. Google은 의견을 받고 새로운 테스트 사례를 발견할 때마다 예시를 계속 추가할 예정입니다.

    • 광고 소재 순환: 광고 소재 ID 및 사용자 상호작용과 같은 데이터를 저장하여 사용자가 여러 사이트에서 어떤 광고 소재를 보게 될지 결정합니다.
    • 게재빈도별 광고 소재 선택: 조회수 데이터를 사용하여 사용자가 여러 사이트에서 보는 광고 소재를 결정합니다.
    • A/B 테스트 실행: 사용자를 실험 그룹에 할당한 후 해당 그룹을 Shared Storage에 저장하여 교차 사이트에서 액세스할 수 있습니다.
    • 알려진 고객을 위한 환경 맞춤설정: 사용자의 등록 상태 또는 기타 사용자 상태를 기반으로 맞춤 콘텐츠와 클릭 유도 문구를 공유합니다.

참여 및 의견 공유

Select URL API 제안은 현재 논의 및 개발 중이며 변경될 수 있습니다.

Select URL API에 대한 의견을 보내주세요.

최신 정보 확인하기

  • 메일링 리스트: 메일링 리스트를 구독하여 Select URL 및 Shared Storage API와 관련된 최신 업데이트 및 공지사항을 확인하세요.

도움이 필요하신가요?